package com.idanchuang.component.base.actuator;

import org.springframework.boot.actuate.health.Health;
import org.springframework.boot.actuate.health.HealthEndpoint;
import org.springframework.boot.actuate.info.Info;
import org.springframework.boot.actuate.info.InfoContributor;

import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.*;

/**
 * @author yjy
 * Created at 2021/6/3 3:22 下午
 */
public class HealthInfoContributor implements InfoContributor {

    private static final ExecutorService executorService = Executors.newSingleThreadExecutor();

    private final HealthEndpoint healthEndpoint;

    public HealthInfoContributor(HealthEndpoint healthEndpoint) {
        this.healthEndpoint = healthEndpoint;
    }

    @Override
    public void contribute(Info.Builder builder) {
        Map<String, Object> data = new HashMap<>();
        try {
            Health health = runWithTimeout(healthEndpoint::health, 1, TimeUnit.SECONDS);
            data.put("status", health.getStatus().getCode());
            data.put("details", health.getDetails());
        } catch (Exception e) {
            data.put("status", "DOWN");
            String detail = "HealthCheck error: " + e.getClass().getName() + ": " + e.getMessage();
            data.put("details", detail);
        }
        builder.withDetail("healthInfo", data);
    }

    /**
     * 执行一个任务并限制其执行时间
     * @param callable 任务
     * @param timeout 超时时间
     * @param timeUnit 时间单位
     * @param <T> 响应对象
     * @return ..
     * @throws Exception e
     */
    private <T> T runWithTimeout(Callable<T> callable, long timeout, TimeUnit timeUnit) throws Exception {
        Future<T> future = executorService.submit(callable);
        return future.get(timeout, timeUnit);
    }

}
